package com.runa.rccprotocol.analysis;

import com.runa.monitor.comm.dto.newComm.AffiliatePanelVO;
import com.runa.monitor.comm.dto.newComm.HotMeterVO;
import com.runa.monitor.comm.dto.newComm.PanelVO;
import com.runa.monitor.comm.dto.newComm.ValveVO;
import com.runa.persistence.RepositoryServicePersis;
import com.runa.protocol.analysis.MetaBufferAnalysis;
import com.runa.protocol.dto.IInterData;
import com.runa.protocol.util.ByteUtil;
import com.runa.rccprotocol.dto.equdata.TerminalCalendarClock;
import com.runa.rccprotocol.dto.equdata.ValveData;
import com.runa.rccprotocol.dto.runa.RunaConcenAffirmDeny;
import com.runa.rccprotocol.dto.runa.RunaConcenResponseData;
import lombok.extern.slf4j.Slf4j;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import static com.runa.rccprotocol.analysis.RunaEquDataAnalysis.heatMeterFaults;

/**
 * @author diandian
 * @Date 2021/12/14 14:22
 */
@Slf4j
public class TianGangEquDataAnalysis extends MetaBufferAnalysis<byte[]> {

    public String netEquNo;

    public static float toKwh(float src, int unit) {
        switch (unit) {
            case 0x02:
                return src / 1000;
            case 0x08:
                return src * 1000;
            case 0x0a:
                return  src * 1000 * 100;
            case 0x01:
                return (float) (src / 1000000000 * 277.8);
            case 0x0b:
                return (float) (src / 1000000 * 277.8);
            case 0x0e:
                return (float) (src / 1000 * 277.8);
            case 0x11:
                return (float) (src * 277.8);
            case 0x13:
                return (float) (src * 100 * 277.8);
            default:
        }
        return src;
    }

    public static float toKw(float src, int unit) {
        switch (unit) {
            case 0x14:
                return src / 1000;
            case 0x15:
                return src / 100;
            case 0x16:
                return src / 10;
            case 0x1a:
                return src * 1000;
            default:
        }
        return src;
    }

    public static float toM3(float src, int unit) {
        switch (unit) {
            case 0x29:
                return src / 1000;
            case 0x2A:
                return src / 100;
            case 0x2B:
                return src / 10;
        }
        return src;
    }

    public static float toM3h(float src, int unit) {
        switch (unit) {
            case 0x32:
                return src / 1000;
            case 0x33:
                return src / 100;
            case 0x34:
                return src / 10;
        }
        return src;
    }

    static List heatMeterFaults(byte b) {
        ArrayList<String> list = new ArrayList<>();
        if ((b >> 5 & 1) == 1) {
            list.add("低压");
        }
        if ((b >> 4 & 1) == 1) {
            list.add("过流");
        }
        if ((b >> 3 & 1) == 1) {
            list.add("坏");
        }
        if ((b >> 2 & 1) == 1) {
            list.add("无水");
        }
        if ((b >> 1 & 1) == 1) {
            list.add("断路");
        }
        if ((b & 1) == 1) {
            list.add("短路");
        }
        return list;
    }


    public HotMeterVO heatMeterData(int idx, byte[] bytes) {
        RunaConcenResponseData responseData = new RunaConcenResponseData();
        HotMeterVO meter = new HotMeterVO();
//        HeatMeterData meter = new HeatMeterData();
        String addr = ByteUtil.byteToHexString(bytes, idx, 4);
        meter.setMeterSerial(addr);
//        hotMeter.set(addr);
        idx += 7;
        int ctrl = bytes[idx] & 0xff;
        if (ctrl == 0x81) {
            idx += 5;
            //todo 厂家编码
            float accCold = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)));
            idx += 4;
            idx++;
//            meter.setSettDateHeatColdVal(toKwh(accCold, bytes[idx++] & 0xff));
            float accHeat = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)));
            idx += 4;
            meter.setAccHeat(toKwh(accHeat, bytes[idx++] & 0xff));
            float power = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)));
            idx += 4;
            meter.setPower(toKw(power, bytes[idx++] & 0xff));
            float flow = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)));
            idx += 4;
            meter.setFlow(toM3h(flow, bytes[idx++] & 0xff));
            float accFlow = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)));
            idx += 4;
            meter.setAccFlow(toM3(accFlow, bytes[idx++]));
            meter.setSupplyTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)) * 0.01));
            idx += 3;
            meter.setReturnTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)) * 0.01));
            idx += 3;
            meter.setWorkTime(Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)));
            idx += 3;
            meter.setMeterDate(TerminalCalendarClock.getInstance(bytes, idx).toDate());
            idx += 8;
            if (bytes[idx] == 0) {
                meter.setStatus("00");
            } else {
                meter.setFaultCode(heatMeterFaults(bytes[idx]));
            }
            meter.setReadDate(new Date());
            responseData.addRepData(meter);
            this.responseData = responseData;
        } else {
            this.responseData = new RunaConcenAffirmDeny(false);
        }
        return meter;
    }

    public boolean metterFill(byte[] data, int length, String netEquNo) {
        if (data[9] == 0x20 && data[14] == 0x00 && data[15] == 0x11 && data[16] == 0x11) {
            log.debug("开始解析南京迈拓报文: {}", data);
            heatMeterData(10, data);
            return true;
        } else {
            return false;
        }

    }

    @Override
    public int fill(byte[] data, int length, String netEquNo) {
        this.netEquNo=netEquNo;
        if (metterFill(data, length, netEquNo)) {
            return 0;
        }

        int begin = 0;
        for (int i = 0; i < length; i++) {
            if ((data[i] & 0xff) == 0x68) {
                if ((data[i + 3] & 0xff) == 0x68) {
                    begin = i;
                    break;
                }
            }
        }
        int len = data[begin + 1] & 0xff;
        if (length < len + begin) return -1;

        int index = begin;
        index += 4;
        int ctr = data[index] & 0xff;
        if (ctr != 0x08) {
            return 0;
        }

        index += 2;
        int ci = data[index] & 0xff;
        if (ci == 0x72) {

            ++index;
            String serial = ByteUtil.byteToHexStringFlip(data, index, 4);

            index += 4;
            String factory = ByteUtil.byteToHexStringFlip(data, index, 2);

            index += 2;
            //05有线，06无线
            int equComType = data[index] & 0xff;

            ++index;
            int equType = data[index] & 0xff;
            switch (equType) {
                case 0x21:
                    return valveData(data, begin, index);
            }
        }

        return 0;
    }

    private int valveData(byte[] data, int begin, int index) {
        if (data[105] != 0x16) {
            return 0;
        }
        //cs校验
        byte checkCs = ByteUtil.sum(data, begin + 4, 100);
        byte cs = data[104];
        if (checkCs != cs) {
            return 0;
        }

        int accessNo = data[++index] & 0xff;
        int status = data[++index] & 0xff;

        ++index;
        int sig = ByteUtil.bcdToInt(data, index, 2, true);

        index += 2;
        int factoryData = data[index] & 0xff;

        ++index;
        String protocolVersion = String.valueOf(ByteUtil.bcdToInt(data, index, 2, true) * 0.01);

        index += 2;
        int valveOpen = data[index] & 0xff;

        //口径
        ++index;

        //报警
        ++index;

        //温控器设定温度，当前温度
        ++index;

        //温控器设定温度为21℃
        ++index;
        int settingTem = data[index] & 0xff;

        //当前温度123.4℃（如果为FFFF，则表示阀门没有获取到温控器的温度）
        ++index;
        double panelTem = ByteUtil.bcdToInt(data, index, 2, false) * 0.1;

        index += 2;
        //温控器当前温度所对应的时间21日03点51分
        String panelTime = ByteUtil.byteToHexStringFlip(data, index, 3);

        //如果为FFh，不解析，否则为阀门状态（解析见表1.2.1.1.10）
        ++index;

        //供暖相关，见表1.2.1.1.2。出厂/供暖/锁定/余额/欠费
        ++index;

        //阀门状态，表1.2.1.1.3。开关命令/执行命令/电机状态/总线带电/无线模块电源
        ++index;

        //阀门运行状态。见表1.2.1.1.4.
        ++index;

        //电机电源电压4.9V
        ++index;

        //门限电压3.2V
        ++index;

        //保留
        ++index;

        //当前时间2013年4月20日14点31分15秒
        ++index;
        String timeStr = ByteUtil.byteToHexStringFlip(data, index, 7);

        //保留
        index += 7;
        String tem1 = ByteUtil.byteToHexString(data, index, 4);

        //保留
        index += 4;
        String tem2 = ByteUtil.byteToHexString(data, index, 4);

        //0表示开度控制，1表示通断控制。
        ++index;
        int valveType = data[index] & 0xff;

        //温控器控制阀门开度范围为10%---50%。
        ++index;
        String valveOpenRange = ByteUtil.byteToHexString(data, index, 2);

        //控器控制阀门开阀时，全关的阀门开启的开度为32%。
        ++index;
        int tem3 = data[index] & 0xff;

        //保留
        ++index;

        //保留
        ++index;
        String tem4 = ByteUtil.byteToHexString(data, index, 4);

        //第1字节表示回水温度修正值（解析方法见表1.2.1.1）。
        index += 4;
        int correct = data[index];
        //后2字节表示回水温度23.4℃。最高位是1表示为负温度
        ++index;
        double returnTem = ByteUtil.bcdToInt(data, index, 2, false) * 0.1;

        //阀门生产码12345678
        index += 2;
        String productionCode = ByteUtil.byteToHexStringFlip(data, index, 4);

        //保留
        index += 4;

        //阀门硬件版本
        ++index;
        int hardwareVersion = ByteUtil.bcdToInt(data, index, 2, false);

        //保留
        index += 2;
        String tem5 = ByteUtil.bcd2str(data, index, 2, true);

        //温控器(硬件版本1234/软件4556)
        index += 2;
        String panelVersion = ByteUtil.bcd2str(data, index, 4, false);

//        无线产品：无线地址12345678。
//        有线产品：不解析（根据第13位的设备识别码判断有线还是无线）
        index += 4;
        String wirelessAddress = ByteUtil.bcd2str(data, index, 4, false);

        //保留
        index += 4;
        String tem6 = ByteUtil.bcd2str(data, index, 2, false);

        //保留
        ++index;

        //阀门电池电压3.6V
        ++index;

        //保留
        ++index;
        int tem7 = ByteUtil.bcdToInt(data, index, 4, false);

        //阀门开关次数12345678次
        index += 4;
        int valveCount = ByteUtil.bcdToInt(data, index, 4, false);

        //自动开关间隔1234分钟
        index += 4;
        int valveOpenCloseTime = ByteUtil.bcdToInt(data, index, 2, false);

        //保留
        index += 2;

        //温控器电池电压3.0V
        ++index;

        //保留
        ++index;
        int tem8 = ByteUtil.bcdToInt(data, index, 2, false);

        //温控器控温范围6℃---28℃
        index += 2;
        int panelTemRange = ByteUtil.bcdToInt(data, index, 2, false);


        ValveVO valveVO = new ValveVO();
//        ValveData valveData = new ValveData();
        valveVO.setReturnTemp((float) returnTem);
        valveVO.setActOpen((float) valveOpen);
        valveVO.setOpenTime((float) (valveOpenCloseTime * 60));
//        valveData.setSetTemperature(settingTem);
        valveVO.setSoftVersion(String.valueOf(hardwareVersion));
        short zero = 0;
//        valveData.setPanel0(new ValveData.Panel(0, 0, (float) panelTem, zero));
//        valveData.setFaults("");
        AffiliatePanelVO panel = new AffiliatePanelVO(0, 0, (float) panelTem, zero);
        panel.setSerial(valveVO.getValveSerial());
        panel.setReadTime(valveVO.getReadTime());
        try {
            panel.setId(RepositoryServicePersis.getCommPanelByNetIdAndSerial(
                    RepositoryServicePersis.getCommNetEquipmentByNetSerial(this.netEquNo).getId(),valveVO.getValveSerial()).getId());
            valveVO.getPanelVOList().add(panel);
        }catch (Exception e){
            log.error("户阀挂面板无面板数据---valveData:{}",valveVO,e);
        }
        //温度带面板使用map
//        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
//        stringObjectHashMap.put("valve",valveVO);
//        stringObjectHashMap.put("panel",panel);
        RunaConcenResponseData responseData = new RunaConcenResponseData();
        responseData.addRepData(valveVO);
        this.responseData = responseData;
        return 0;
    }

    public static void main(String[] args) {
//        String data = "F8 00 00 0E 00 81 47 74 04 00 48 00 00 00 00 00 10 00 9E 16";
//        String data = "01 03 2C 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 60 0C 3A 0B E4 00 00 04 7D 07 E2 00 08 00 0E 00 10 00 09 00 2C 00 00 00 01 CE 7F";
        String data = "F800093FFF008178152030942695001111812E901FB80000000005213901000518020000152705000032335615002A4634000338003938005747160204242000001D163516";
        String control0 = "68 0C 0C 68 08 00 78 0C 79 17 64 11 97 0F 4C 50 D3 16".replace(" ", "");
        String control1 = "68 0C 0C 68 08 00 78 0C 79 48 64 11 97 0F 4C 50 04 16".replace(" ", "");
        byte[] dataByte = ByteUtil.hexStringToByte(data);
        System.out.println(ByteUtil.byteToHexString(dataByte));
        TianGangEquDataAnalysis analysis = new TianGangEquDataAnalysis();
        TianGangAnalysis tianGangAnalysis = new TianGangAnalysis(analysis);
        tianGangAnalysis.fill(dataByte, dataByte.length,"");
        IInterData gain = analysis.gain();
        System.out.println();
    }
}
